const DEFAULT_TRIGGER = 'shift';
const ALLOW_EVENTS = ['shift', 'ctrl', 'alt'];
import {flatten} from "@/utils/utils";

export const SELECTED_STATE = 'selected'

export function clickSelect(G6) {
    G6.registerBehavior('click-select', {
        getDefaultCfg() {
            return {
                multiple: true,
                trigger: DEFAULT_TRIGGER,
            };
        },
        getEvents() {
            if (!this.multiple) {
                return {
                    'node:click': 'onClick',
                    'edge:click': 'onClick',
                    'canvas:click': 'onCanvasClick'
                };
            }
            return {
                'node:click': 'onClick',
                'edge:click': 'onClick',
                'canvas:click': 'onCanvasClick',
                keyup: 'onKeyUp',
                keydown: 'onKeyDown'
            };
        },
        onClick(e) {
            const self = this;
            const item = e.item;
            const graph = self.graph;
            const autoPaint = graph.get('autoPaint');
            graph.setAutoPaint(false);

            // 当前是否选择有变化
            let selectChangeFlag = false

            if (!self.keydown || !self.multiple) {
                const selected = this.getSelected()

                flatten(Object.values(selected)).forEach(n => {
                    if (n !== item) {
                        if (n.hasState(SELECTED_STATE)) {
                            selectChangeFlag = true
                            graph.setItemState(n, SELECTED_STATE, false);
                        }
                    }
                })
            }
            if (item.hasState(SELECTED_STATE)) {
                return
            } else {
                if (self.shouldUpdate.call(self, e)) {
                    selectChangeFlag = true
                    graph.setItemState(item, SELECTED_STATE, true);
                }
                graph.emit('nodeselectchange', {target: item, select: true});
            }
            if (selectChangeFlag) {
                this.emitSelectChange()
            }
            graph.setAutoPaint(autoPaint);
            graph.paint();
        },
        onCanvasClick() {

            if (this.keydown) {
                return
            }

            const graph = this.graph;
            const autoPaint = graph.get('autoPaint');
            graph.setAutoPaint(false);
            const selected = this.getSelected()

            // 当前是否选择有变化
            let selectChangeFlag = false

            flatten(Object.values(selected)).forEach(n => {
                if (n.hasState(SELECTED_STATE)) {
                    selectChangeFlag = true
                    graph.setItemState(n, SELECTED_STATE, false);
                }
            });
            if (selectChangeFlag) {
                this.emitSelectChange(true)
            }

            graph.paint();
            graph.setAutoPaint(autoPaint);
        },
        onKeyDown(e) {
            const code = e.key;
            if (ALLOW_EVENTS.indexOf(code.toLowerCase()) > -1) {
                this.keydown = true;
            } else {
                this.keydown = false;
            }
        },
        onKeyUp() {
            this.keydown = false;
        },

        getSelected() {
            return getSelected(this.graph)
        },
        emitSelectChange(isClear: boolean = false) {

            if (isClear) {
                this.selectChange([], [])
            } else {
                const graph = this.graph;
                const nodes = graph.findAllByState('node', SELECTED_STATE)
                const edges = graph.findAllByState('edge', SELECTED_STATE)
                this.selectChange(nodes, edges)
            }
        },
        selectChange(nodes: any[], edges: any[]) {
            this.graph.emit('select-change', {nodes, edges})
        },
    })
}

export function getSelected(graph: any) {
    return {
        nodes: graph.findAllByState('node', SELECTED_STATE),
        edges: graph.findAllByState('edge', SELECTED_STATE)
    }
}
